/*
 * Copyright (c) Ulrich Hilger, http://dev.uhilger.de, all rights reserved.
 *
 * Published under the terms and conditions of the Apache License 2.0,
 * see http://www.apache.org/licenses/LICENSE-2.0
 */

package de.uhilger.servicehub.view;

import de.uhilger.app.ui.GridBagHelper;
import de.uhilger.servicehub.ServiceHub;
import de.uhilger.servicehub.model.UserStore;
import de.uhilger.servicehub.server.ServiceHubRole;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * <p>Panel to edit roles of a ServiceHub</p>
 *
 * @author Ulrich Hilger, <a href="http://dev.uhilger.de" target="_blank">http://dev.uhilger.de</a>
 * @author Published under the terms and conditions of
 * the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a>
 */
public class RolePanel extends JPanel implements ActionListener, ListSelectionListener {

  private static final String RN_ROLE_PANEL_NEW_BUTTON_LABEL = "rolePanelNewButtonLabel";
  private static final String RN_ROLE_PANEL_DEL_BUTTON_LABEL = "rolePanelDelButtonLabel";
  private static final String RN_ROLE_PANEL_SAVE_BUTTON_LABEL = "rolePanelSaveButtonLabel";
  private static final String RN_ROLE_PANEL_CANCEL_BUTTON_LABEL = "rolePanelCancelButtonLabel";
  private static final String RN_ROLE_PANEL_ROLE_NAME_LABEL = "rolePanelRoleNameLabel";

  private JList roleList;
  private JButton newBtn;
  private JButton delBtn;
  private JTextField roleName;
  private JButton saveBtn;
  private JScrollPane sp;
  private JPanel rolePanel;
  private JButton cancelBtn;
  private UserStore store;
  private String oldRoleId = null;
  private boolean isNewRole = false;

  /**
   * Create a new object of class RolePanel
   * @param bundle  where to take strings from
   */
  public RolePanel(ResourceBundle bundle) {
    super();
    buildUi(bundle);
  }

  /**
   * Set the user store this panel reads from and writes to
   * @param store  the user store
   */
  public void setUserStore(UserStore store) {
    this.store = store;
    updateRoleList();
  }

  /**
   * Refresh the list of roles to reflect changes
   */
  private void updateRoleList() {
    if (store != null) {
      try {
        roleList.removeListSelectionListener(this);
        roleList = new JList(store.getRoles().toArray());
        roleList.addListSelectionListener(this);
        delBtn.setEnabled(false);
        sp.setViewportView(roleList);
      } catch (Exception ex) {
        ServiceHub.logStackTrace(ex, getClass());
      }
    }
  }

  /**
   * Create the user interface of this panel
   * @param owner  the ServiceHub that panel edits roles for
   */
  private void buildUi(ResourceBundle bundle) {
    roleList = new JList();
    roleList.addListSelectionListener(this);
    sp = new JScrollPane(roleList);

    newBtn = new JButton(bundle.getString(RN_ROLE_PANEL_NEW_BUTTON_LABEL));
    newBtn.addActionListener(this);
    delBtn = new JButton(bundle.getString(RN_ROLE_PANEL_DEL_BUTTON_LABEL));
    delBtn.addActionListener(this);
    delBtn.setEnabled(false);
    JPanel buttonPanel = new JPanel();
    buttonPanel.add(newBtn);
    buttonPanel.add(delBtn);

    JPanel roleListPanel = new JPanel(new BorderLayout());
    roleListPanel.add(sp, BorderLayout.CENTER);
    roleListPanel.add(buttonPanel, BorderLayout.SOUTH);

    GridBagHelper gbh = new GridBagHelper();
    GridBagLayout g = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();

    rolePanel = new JPanel(g);
    rolePanel.setEnabled(false);

    JLabel lb = new JLabel(bundle.getString(RN_ROLE_PANEL_ROLE_NAME_LABEL));
    gbh.addGridBagComponent(rolePanel, lb, g, c, 0, 0, GridBagConstraints.EAST);

    roleName = new JTextField();
    gbh.addGridBagComponent(rolePanel, roleName, g, c, 1, 0, GridBagConstraints.WEST,
      1, 1, GridBagConstraints.HORIZONTAL, 1, 1);

    saveBtn = new JButton(bundle.getString(RN_ROLE_PANEL_SAVE_BUTTON_LABEL));
    saveBtn.addActionListener(this);
    cancelBtn = new JButton(bundle.getString(RN_ROLE_PANEL_CANCEL_BUTTON_LABEL));
    cancelBtn.addActionListener(this);

    JPanel saveCancelPanel = new JPanel();
    saveCancelPanel.add(cancelBtn);
    saveCancelPanel.add(saveBtn);
    gbh.addGridBagComponent(rolePanel, saveCancelPanel, g, c, 1, 1, GridBagConstraints.EAST);

    JPanel centerPanel = new JPanel(new BorderLayout());
    centerPanel.add(rolePanel, BorderLayout.NORTH);
    centerPanel.setBorder(new EmptyBorder(12, 12, 12, 12));

    setLayout(new BorderLayout());
    add(roleListPanel, BorderLayout.WEST);
    add(centerPanel, BorderLayout.CENTER);

    setBorder(new EmptyBorder(12, 12, 12, 12));

    endRoleEdit();
  }

  /**
   * Initiate to edit a role, i.e. enable respective controls
   */
  private void startRoleEdit() {
    rolePanel.setEnabled(true);
    roleName.setEnabled(true);
    saveBtn.setEnabled(true);
    cancelBtn.setEnabled(true);
    roleName.requestFocus();
  }

  /**
   * End to edit a role, i.e. disable respective controls
   */
  private void endRoleEdit() {
    rolePanel.setEnabled(false);
    roleName.setText("");
    roleName.setEnabled(false);
    saveBtn.setEnabled(false);
    cancelBtn.setEnabled(false);
  }

  /**
   * Create the role whose name is entered in the role name control
   */
  private void newRole() {
    ServiceHubRole role = new ServiceHubRole();
    role.setRoleName(roleName.getText());
    try {
      store.createRole(role);
    } catch (Exception ex) {
      ServiceHub.logStackTrace(ex, getClass());
    }
    endRoleEdit();
  }

  /**
   * Delete the role whose name is entered in the role name control
   */
  private void delRole() {
    try {
      store.deleteRole(roleName.getText());
    } catch (Exception ex) {
      ServiceHub.logStackTrace(ex, getClass());
    }
  }

  /**
   * Save the role whose name is entered in the role name control
   */
  private void saveRole() {
    ServiceHubRole role = new ServiceHubRole();
    role.setRoleName(roleName.getText());
    try {
      store.storeRole(oldRoleId, role);
    } catch (Exception ex) {
      ServiceHub.logStackTrace(ex, getClass());
    }
    endRoleEdit();
  }

  /* --------------- ActionListener ---------------- */

  /**
   * Handle actions from this panels components
   * @param e  the action event to handle
   */
  public void actionPerformed(ActionEvent e) {
    Object src = e.getSource();
    if (src.equals(newBtn)) {
      isNewRole = true;
      startRoleEdit();
    } else if (src.equals(delBtn)) {
      delRole();
      updateRoleList();
      endRoleEdit();
    } else if (src.equals(saveBtn)) {
      if (isNewRole) {
        newRole();
      } else {
        saveRole();
      }
      updateRoleList();
    } else if(src.equals(cancelBtn)) {
      roleList.clearSelection();
      delBtn.setEnabled(false);
      endRoleEdit();
    }
  }

  /* ---------------- ListSelectionListener ------------------- */

  /**
   * Handle selection events from the role list
   * @param e  the event to handle
   */
  public void valueChanged(ListSelectionEvent e) {
    Object src = e.getSource();
    if (src.equals(roleList)) {
      Object selectedValue = roleList.getSelectedValue();
      if (selectedValue != null) {
        isNewRole = false;
        oldRoleId = selectedValue.toString();
        roleName.setText(oldRoleId);
        delBtn.setEnabled(true);
        startRoleEdit();
      }
    }
  }
}
